/*
** malloc.c for  in /home/alxevo/Documents/projets/malloc/malloc_norme
** 
** Made by Thibault Ravera
** Login   <ravera_t@epitech.net>
** 
** Started on  Fri Feb  3 22:04:19 2012 Thibault Ravera
** Last update Sun Feb  5 20:29:30 2012 Thibault Ravera
*/

#include	"malloc.h"

void		*head_heap_ori = NULL;
void		*head_heap_cur = NULL;
void		*bins[SIZE_ARRAY_BINS];
pthread_mutex_t	lock_list = PTHREAD_MUTEX_INITIALIZER;

void		new_data_range()
{
  void		*header;
  void		*save_last_head;

  save_last_head = head_heap_cur;
  if ((head_heap_cur = sbrk(0)) == (void*) -1)
    abort();
  if ((header = sbrk(_MYHEADER_INFO_SIZE + _MYSIZE_T)) == (void*) -1)
    abort();
  DATA_RANGE(header)->head = head_heap_cur;
  DATA_RANGE(header)->queue = head_heap_cur
    + (_MYHEADER_INFO_SIZE + _MYSIZE_T);
  if (DATA_RANGE(head_heap_cur)->queue == NULL ||
      DATA_RANGE(head_heap_cur)->head == NULL ||
      (save_last_head && DATA_RANGE(save_last_head)->queue > head_heap_cur))
    abort();
  if (save_last_head)
    DATA_RANGE(save_last_head)->next = head_heap_cur;
}

void		mymalloc_init()
{
  int		i = 0;

  while (i < SIZE_ARRAY_BINS)
    bins[i++] = NULL;
  if ((head_heap_ori = sbrk(0)) == (void*) -1)
    abort();
  new_data_range();
  pthread_mutex_init(&lock_list, NULL);
}

void		*request_more_memory(size_t size)
{
  void		*ptr;

  pthread_mutex_lock(&lock_list);
  ptr = sbrk(size);
  if (ptr == (void*) -1)
    {
      pthread_mutex_unlock(&lock_list);
      return (NULL);
    }
  ((t_header*)(ptr - _MYHEADER_SIZE))->size |= size;
  DATA_RANGE(head_heap_cur)->queue = (ptr + size);
  pthread_mutex_unlock(&lock_list);
  return (ptr);
}

void		*malloc(size_t size)
{
  void		*ptr;
  size_t	real_size;

  pthread_mutex_lock(&lock_list);
  if (head_heap_ori == NULL)
    mymalloc_init();
  if (size == 0)
    {
      pthread_mutex_unlock(&lock_list);
      return (NULL);
    }
  if (DATA_RANGE(head_heap_cur)->queue != sbrk(0))
    new_data_range();
  if ((real_size = MEMORY_REQUEST(NBLOCKS(size))) < _MIN_CHUNK)
    real_size = _MIN_CHUNK;
  if ((ptr = use_free_list(real_size)))
    {
      pthread_mutex_unlock(&lock_list);
      return (ptr);
    }
  pthread_mutex_unlock(&lock_list);
  return (request_more_memory(real_size));
}
